#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include <assert.h>
#include <unistd.h>
#include <syserr.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/epoll.h>
#include <pthread.h>
#include <utils.h>
#include "dlist.h"
#include "object.h"
#include "printk.h"


static const char *obj_type_str[OBJ_TYPE_NR] =
{
    [OBJ_LOOP] = "LOOP", [OBJ_DEV] = "DEV", [OBJ_CHN] = "CHN",
    [OBJ_APP_FAT] = "APP_FAT", [OBJ_APP] = "APP",
};

static struct list_head objs_list[OBJ_TYPE_NR] =
{
    [OBJ_LOOP]  = LIST_HEAD_INIT(objs_list[OBJ_LOOP]),
    [OBJ_DEV]   = LIST_HEAD_INIT(objs_list[OBJ_DEV]),
    [OBJ_CHN]   = LIST_HEAD_INIT(objs_list[OBJ_CHN]),
    [OBJ_APP_FAT] = LIST_HEAD_INIT(objs_list[OBJ_APP_FAT]),
    [OBJ_APP]   = LIST_HEAD_INIT(objs_list[OBJ_APP]),
};

static pthread_mutex_t obj_mux = PTHREAD_MUTEX_INITIALIZER;
struct list_head *obj_head(obj_type_t type)
{
    return &objs_list[type];
}

object_t *obj_find_by_obj(obj_type_t type, object_t *obj)
{
    object_t *iter;

    list_for_each_entry(iter, &objs_list[type], entry)
    if (iter == obj)
        return iter;
    return NULL;
}

void obj_init(object_t *obj, obj_type_t type, const char *name)
{
    memset(obj, 0, sizeof(object_t));

    INIT_LIST_HEAD(&obj->entry);
    obj->type  = type;
    obj->en    = 1;
    svc__strscpy(obj->name, name, sizeof(obj->name));
}

int obj_add(object_t *obj, obj_type_t type, const char *name)
{
    if (obj_find_by_obj(type, obj))
        return -EEXIST;

    obj_init(obj, type, name);

    pthread_mutex_lock(&obj_mux);
    list_add_tail(&obj->entry, &objs_list[type]);
    pthread_mutex_unlock(&obj_mux);
    return 0;
}

void obj_del(object_t *obj)
{
    pthread_mutex_lock(&obj_mux);
    list_del(&obj->entry);
    pthread_mutex_unlock(&obj_mux);
}

object_t *obj_find_with_type(obj_type_t type, const char *name)
{
    object_t *iter;

    list_for_each_entry(iter, &objs_list[type], entry)
    if (!strncmp(iter->name, name, OBJECT_NAME_SIZE))
        return iter;
    return NULL;
}

object_t *obj_find(const char *name)
{
    int i;

    for (i = 0; i < OBJ_TYPE_NR; i++)
    {
        object_t *obj = obj_find_with_type((obj_type_t)i, name);
        if (obj) return obj;
    }
    return NULL;
}

void obj_dump(void)
{
    int i;
    object_t *iter;

    printk("|====================================|\r\n");
    printk("|           name    |type|init|active|\r\n");
    printk("|====================================|\r\n");

    for (i = 0; i < OBJ_TYPE_NR; i++)
    {
        list_for_each_entry(iter, &objs_list[i], entry)
        {
            printk("|%19s|%4s|%4d|%6d|\r\n",
                   iter->name, obj_type_str[iter->type], iter->init, iter->active);
        }
    }
    printk("|====================================|\r\n");
}
